home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The Very Best of Atari Inside
/
The Very Best of Atari Inside 1.iso
/
mint
/
mint110s
/
shmfs.c
< prev
next >
Wrap
C/C++ Source or Header
|
1994-02-11
|
15KB
|
707 lines
/*
Copyright 1992,1993 Eric R. Smith.
Copyright 1993,1994 Atari Corporation.
All rights reserved.
*/
/* Shared memory file system */
#include "mint.h"
static long ARGS_ON_STACK shm_root P_((int drv, fcookie *fc));
static long ARGS_ON_STACK shm_creat P_((fcookie *dir, const char *name, unsigned mode,
int attrib, fcookie *fc));
static long ARGS_ON_STACK shm_lookup P_((fcookie *dir, const char *name, fcookie *fc));
static long ARGS_ON_STACK shm_getxattr P_((fcookie *fc, XATTR *xattr));
static long ARGS_ON_STACK shm_chattr P_((fcookie *fc, int attrib));
static long ARGS_ON_STACK shm_chown P_((fcookie *fc, int uid, int gid));
static long ARGS_ON_STACK shm_chmode P_((fcookie *fc, unsigned mode));
static long ARGS_ON_STACK shm_rmdir P_((fcookie *dir, const char *name));
static long ARGS_ON_STACK shm_remove P_((fcookie *dir, const char *name));
static long ARGS_ON_STACK shm_getname P_((fcookie *root, fcookie *dir,
char *pathname, int size));
static long ARGS_ON_STACK shm_rename P_((fcookie *olddir, char *oldname,
fcookie *newdir, const char *newname));
static long ARGS_ON_STACK shm_opendir P_((DIR *dirh, int flags));
static long ARGS_ON_STACK shm_readdir P_((DIR *dirh, char *nm, int nmlen, fcookie *));
static long ARGS_ON_STACK shm_rewinddir P_((DIR *dirh));
static long ARGS_ON_STACK shm_closedir P_((DIR *dirh));
static long ARGS_ON_STACK shm_pathconf P_((fcookie *dir, int which));
static long ARGS_ON_STACK shm_dfree P_((fcookie *dir, long *buf));
static DEVDRV * ARGS_ON_STACK shm_getdev P_((fcookie *fc, long *devsp));
static long ARGS_ON_STACK shm_open P_((FILEPTR *f));
static long ARGS_ON_STACK shm_write P_((FILEPTR *f, const char *buf, long bytes));
static long ARGS_ON_STACK shm_read P_((FILEPTR *f, char *buf, long bytes));
static long ARGS_ON_STACK shm_lseek P_((FILEPTR *f, long where, int whence));
static long ARGS_ON_STACK shm_ioctl P_((FILEPTR *f, int mode, void *buf));
static long ARGS_ON_STACK shm_datime P_((FILEPTR *f, short *time, int rwflag));
static long ARGS_ON_STACK shm_close P_((FILEPTR *f, int pid));
/* dummy routines from biosfs.c */
extern long ARGS_ON_STACK null_select P_((FILEPTR *f, long p, int mode));
extern void ARGS_ON_STACK null_unselect P_((FILEPTR *f, long p, int mode));
static short shmtime, shmdate;
#define SHMNAME_MAX 15
typedef struct shmfile {
struct shmfile *next;
char filename[SHMNAME_MAX+1];
int uid, gid;
short time, date;
unsigned mode;
int inuse;
MEMREGION *reg;
} SHMFILE;
SHMFILE *shmroot = 0;
DEVDRV shm_device = {
shm_open, shm_write, shm_read, shm_lseek, shm_ioctl, shm_datime,
shm_close, null_select, null_unselect
};
FILESYS shm_filesys = {
(FILESYS *)0,
FS_LONGPATH,
shm_root,
shm_lookup, shm_creat, shm_getdev, shm_getxattr,
shm_chattr, shm_chown, shm_chmode,
nomkdir, shm_rmdir, shm_remove, shm_getname, shm_rename,
shm_opendir, shm_readdir, shm_rewinddir, shm_closedir,
shm_pathconf, shm_dfree,
nowritelabel, noreadlabel, nosymlink, noreadlink, nohardlink,
nofscntl, nodskchng
};
long ARGS_ON_STACK
shm_root(drv, fc)
int drv;
fcookie *fc;
{
if ((unsigned)drv == SHMDRV) {
fc->fs = &shm_filesys;
fc->dev = drv;
fc->index = 0L;
return 0;
}
fc->fs = 0;
return EINTRN;
}
static long ARGS_ON_STACK
shm_lookup(dir, name, fc)
fcookie *dir;
const char *name;
fcookie *fc;
{
SHMFILE *s;
if (dir->index != 0) {
DEBUG(("shm_lookup: bad directory"));
return EPTHNF;
}
/* special case: an empty name in a directory means that directory */
/* so does "." */
if (!*name || (name[0] == '.' && name[1] == 0)) {
*fc = *dir;
return 0;
}
/* another special case: ".." could be a mount point */
if (!strcmp(name, "..")) {
*fc = *dir;
return EMOUNT;
}
for (s = shmroot; s; s = s->next) {
if (!stricmp(s->filename,name))
break;
}
if (!s) {
DEBUG(("shm_lookup: name not found"));
return EFILNF;
} else {
fc->index = (long)s;
fc->fs = &shm_filesys;
fc->dev = SHMDRV;
}
return 0;
}
static long ARGS_ON_STACK
shm_getxattr(fc, xattr)
fcookie *fc;
XATTR *xattr;
{
SHMFILE *s;
xattr->blksize = 1;
if (fc->index == 0) {
/* the root directory */
xattr->index = 0;
xattr->dev = xattr->rdev = SHMDRV;
xattr->nlink = 1;
xattr->uid = xattr->gid = 0;
xattr->size = xattr->nblocks = 0;
xattr->mtime = xattr->atime = xattr->ctime = shmtime;
xattr->mdate = xattr->adate = xattr->cdate = shmdate;
xattr->mode = S_IFDIR | DEFAULT_DIRMODE;
xattr->attr = FA_DIR;
return 0;
}
s = (SHMFILE *)fc->index;
xattr->index = (long) s;
xattr->dev = SHMDRV;
xattr->rdev = PROC_RDEV_BASE | 0;
xattr->uid = s->uid; xattr->gid = s->gid;
if (s->reg) {
xattr->size = xattr->nblocks = s->reg->len;
xattr->nlink = s->reg->links + 1;
} else {
xattr->size = xattr->nblocks = 0;
xattr->nlink = 1;
}
xattr->mtime = xattr->ctime = xattr->atime = s->time;
xattr->mdate = xattr->cdate = xattr->adate = s->date;
xattr->mode = s->mode;
xattr->attr = (s->mode & (S_IWUSR|S_IWGRP|S_IWOTH)) ? 0 :
FA_RDONLY;
return 0;
}
static long ARGS_ON_STACK
shm_chattr(fc, attrib)
fcookie *fc;
int attrib;
{
SHMFILE *s;
s = (SHMFILE *)fc->index;
if (!s) return EACCDN;
if (attrib & FA_RDONLY) {
s->mode &= ~(S_IWUSR|S_IWGRP|S_IWOTH);
} else if ( !(s->mode & (S_IWUSR|S_IWGRP|S_IWOTH)) ) {
s->mode |= (S_IWUSR|S_IWGRP|S_IWOTH);
}
return 0;
}
static long ARGS_ON_STACK
shm_chown(fc, uid, gid)
fcookie *fc;
int uid, gid;
{
SHMFILE *s;
s = (SHMFILE *)fc->index;
if (!s)
return EACCDN;
s->uid = uid;
s->gid = gid;
return 0;
}
static long ARGS_ON_STACK
shm_chmode(fc, mode)
fcookie *fc;
unsigned mode;
{
SHMFILE *s;
s = (SHMFILE *)fc->index;
if (!s)
return EINVFN;
s->mode = mode;
return 0;
}
static long ARGS_ON_STACK
shm_rmdir(dir, name)
fcookie *dir;
const char *name;
{
UNUSED(dir); UNUSED(name);
return EPTHNF;
}
static long ARGS_ON_STACK
shm_remove(dir, name)
fcookie *dir;
const char *name;
{
SHMFILE *s, **old;
if (dir->index != 0)
return EPTHNF;
old = &shmroot;
for (s = shmroot; s; s = s->next) {
if (!stricmp(s->filename, name))
break;
old = &s->next;
}
if (!s)
return EFILNF;
if (s->inuse)
return EACCDN;
*old = s->next;
s->reg->links--;
if (s->reg->links <= 0) {
free_region(s->reg);
}
kfree(s);
shmtime = timestamp;
shmdate = datestamp;
return 0;
}
static long ARGS_ON_STACK
shm_getname(root, dir, pathname, size)
fcookie *root, *dir; char *pathname;
int size;
{
UNUSED(root); UNUSED(dir);
/* BUG: 'size' should be used in a more meaningful way */
if (size <= 0) return ERANGE;
*pathname = 0;
return 0;
}
static long ARGS_ON_STACK
shm_rename(olddir, oldname, newdir, newname)
fcookie *olddir;
char *oldname;
fcookie *newdir;
const char *newname;
{
SHMFILE *s;
if (olddir->index != 0 || newdir->index != 0)
return EPTHNF;
/* verify that "newname" doesn't exist */
for (s = shmroot; s; s = s->next)
if (!stricmp(s->filename, newname))
return EACCDN;
for (s = shmroot; s; s = s->next)
if (!stricmp(s->filename, oldname))
break;
if (!s)
return EFILNF;
strncpy(s->filename, newname, SHMNAME_MAX);
shmtime = timestamp;
shmdate = datestamp;
return 0;
}
static long ARGS_ON_STACK
shm_opendir(dirh, flags)
DIR *dirh;
int flags;
{
UNUSED(flags);
dirh->index = 0;
return 0;
}
static long ARGS_ON_STACK
shm_readdir(dirh, name, namelen, fc)
DIR *dirh;
char *name;
int namelen;
fcookie *fc;
{
int i;
int giveindex = (dirh->flags == 0);
SHMFILE *s;
s = shmroot;
i = dirh->index++;
while (i > 0 && s != 0) {
s = s->next;
--i;
}
if (!s)
return ENMFIL;
fc->index = (long)s;
fc->fs = &shm_filesys;
fc->dev = SHMDRV;
if (giveindex) {
namelen -= (int)sizeof(long);
if (namelen <= 0) return ERANGE;
*((long *)name) = (long)s;
name += sizeof(long);
}
if (namelen < strlen(s->filename))
return ENAMETOOLONG;
strcpy(name, s->filename);
return 0;
}
static long ARGS_ON_STACK
shm_rewinddir(dirh)
DIR *dirh;
{
dirh->index = 0;
return 0;
}
static long ARGS_ON_STACK
shm_closedir(dirh)
DIR *dirh;
{
UNUSED(dirh);
return 0;
}
static long ARGS_ON_STACK
shm_pathconf(dir, which)
fcookie *dir;
int which;
{
UNUSED(dir);
switch(which) {
case -1:
return DP_MAXREQ;
case DP_IOPEN:
return UNLIMITED; /* no internal limit on open files */
case DP_MAXLINKS:
return 1; /* we don't have hard links */
case DP_PATHMAX:
return PATH_MAX; /* max. path length */
case DP_NAMEMAX:
return SHMNAME_MAX; /* max. length of individual name */
case DP_ATOMIC:
return UNLIMITED; /* all writes are atomic */
case DP_TRUNC:
return DP_AUTOTRUNC; /* file names are truncated */
case DP_CASE:
return DP_CASEINSENS; /* case preserved, but ignored */
default:
return EINVFN;
}
}
static long ARGS_ON_STACK
shm_dfree(dir, buf)
fcookie *dir;
long *buf;
{
long size;
/* "sector" size is the size of the smallest amount of memory that can be
allocated. see mem.h for the definition of ROUND
*/
long secsiz = ROUND(1);
UNUSED(dir);
size = tot_rsize(core, 0) + tot_rsize(alt, 0);
*buf++ = size/secsiz; /* number of free clusters */
size = tot_rsize(core, 1) + tot_rsize(alt, 1);
*buf++ = size/secsiz; /* total number of clusters */
*buf++ = secsiz; /* sector size (bytes) */
*buf = 1; /* cluster size (in sectors) */
return 0;
}
static DEVDRV * ARGS_ON_STACK
shm_getdev(fc, devsp)
fcookie *fc;
long *devsp;
{
SHMFILE *s;
s = (SHMFILE *)fc->index;
*devsp = (long)s;
return &shm_device;
}
/*
* create a shared memory region
*/
static long ARGS_ON_STACK
shm_creat(dir, name, mode, attrib, fc)
fcookie *dir;
const char *name;
unsigned mode;
int attrib;
fcookie *fc;
{
SHMFILE *s;
UNUSED(attrib);
/*
* see if the name already exists
*/
for (s = shmroot; s; s = s->next) {
if (!stricmp(s->filename, name)) {
DEBUG(("shm_creat: file exists"));
return EACCDN;
}
}
s = (SHMFILE *)kmalloc(SIZEOF(SHMFILE));
if (!s)
return ENSMEM;
s->inuse = 0;
strncpy(s->filename, name, SHMNAME_MAX);
s->filename[SHMNAME_MAX] = 0;
s->uid = curproc->ruid;
s->gid = curproc->rgid;
s->mode = mode;
s->next = shmroot;
s->reg = 0;
s->time = shmtime = timestamp;
s->date = shmdate = datestamp;
shmroot = s;
fc->fs = &shm_filesys;
fc->index = (long)s;
fc->dev = dir->dev;
return 0;
}
/*
* Shared memory device driver
*/
/*
* BUG: file locking and the O_SHMODE restrictions are not implemented
* for shared memory
*/
static long ARGS_ON_STACK
shm_open(f)
FILEPTR *f;
{
SHMFILE *s;
s = (SHMFILE *)f->devinfo;
s->inuse++;
return 0;
}
static long ARGS_ON_STACK
shm_write(f, buf, nbytes)
FILEPTR *f; const char *buf; long nbytes;
{
SHMFILE *s;
char *where;
long bytes_written = 0;
s = (SHMFILE *)f->devinfo;
if (!s->reg)
return 0;
if (nbytes + f->pos > s->reg->len)
nbytes = s->reg->len - f->pos;
where = (char *)s->reg->loc + f->pos;
/* BUG: memory read/writes should check for valid addresses */
TRACE(("shm_write: %ld bytes to %lx", nbytes, where));
while (nbytes-- > 0) {
*where++ = *buf++;
bytes_written++;
}
f->pos += bytes_written;
s->time = timestamp;
s->date = datestamp;
return bytes_written;
}
static long ARGS_ON_STACK
shm_read(f, buf, nbytes)
FILEPTR *f; char *buf; long nbytes;
{
SHMFILE *s;
char *where;
long bytes_read = 0;
s = (SHMFILE *)f->devinfo;
if (!(s->reg))
return 0;
if (nbytes + f->pos > s->reg->len)
nbytes = s->reg->len - f->pos;
where = (char *)s->reg->loc + f->pos;
TRACE(("shm_read: %ld bytes from %lx", nbytes, where));
while (nbytes-- > 0) {
*buf++ = *where++;
bytes_read++;
}
f->pos += bytes_read;
return bytes_read;
}
/*
* shm_ioctl: currently, the only IOCTL's available are:
* SHMSETBLK: set the address of the shared memory file. This
* call may only be made once per region, and then only
* if the region is open for writing.
* SHMGETBLK: get the address of the shared memory region. This
* call fails (returns 0) if SHMSETBLK has not been
* called yet for this shared memory file.
*/
static long ARGS_ON_STACK
shm_ioctl(f, mode, buf)
FILEPTR *f; int mode; void *buf;
{
SHMFILE *s;
MEMREGION *m;
int i;
long r;
s = (SHMFILE *)f->devinfo;
switch(mode) {
case SHMSETBLK:
if (s->reg) {
DEBUG(("Fcntl: SHMSETBLK already performed for %s",
s->filename));
return ERANGE;
}
if ((f->flags & O_RWMODE) == O_RDONLY) {
DEBUG(("Fcntl: SHMSETBLK: %s was opened read-only",
s->filename));
return EACCDN;
}
/* find the memory region to be attached */
m = 0;
for (i = curproc->num_reg - 1; i >= 0; i--) {
if (curproc->addr[i] == (virtaddr)buf) {
m = curproc->mem[i];
break;
}
}
if (!m || !buf) {
DEBUG(("Fcntl: SHMSETBLK: bad address %lx", buf));
return EIMBA;
}
m->links++;
s->reg = m;
return 0;
case SHMGETBLK:
if ((m = s->reg) == 0) {
DEBUG(("Fcntl: no address for SHMGETBLK"));
return 0;
}
/* check for memory limits */
if (curproc->maxmem) {
if (m->len > curproc->maxmem - memused(curproc)) {
DEBUG(("Fcntl: SHMGETBLK would violate memory limits"));
return 0;
}
}
return (long)attach_region(curproc, m);
case FIONREAD:
case FIONWRITE:
if (s->reg == 0) {
r = 0;
} else {
r = s->reg->len - f->pos;
if (r < 0) r = 0;
}
*((long *)buf) = r;
return 0;
default:
DEBUG(("shmfs: bad Fcntl command"));
}
return EINVFN;
}
static long ARGS_ON_STACK
shm_lseek(f, where, whence)
FILEPTR *f; long where; int whence;
{
long newpos, maxpos;
SHMFILE *s;
s = (SHMFILE *)f->devinfo;
if (s->reg)
maxpos = s->reg->len;
else
maxpos = 0;
switch(whence) {
case 0:
newpos = where;
break;
case 1:
newpos = f->pos + where;
break;
case 2:
newpos = maxpos + where;
break;
default:
return EINVFN;
}
if (newpos < 0 || newpos > maxpos)
return ERANGE;
f->pos = newpos;
return newpos;
}
static long ARGS_ON_STACK
shm_datime(f, timeptr, rwflag)
FILEPTR *f;
short *timeptr;
int rwflag;
{
SHMFILE *s;
s = (SHMFILE *)f->devinfo;
if (rwflag) {
s->time = *timeptr++;
s->date = *timeptr;
} else {
*timeptr++ = s->time;
*timeptr = s->date;
}
return 0;
}
static long ARGS_ON_STACK
shm_close(f, pid)
FILEPTR *f;
int pid;
{
SHMFILE *s;
UNUSED(pid);
if (f->links <= 0) {
s = (SHMFILE *)f->devinfo;
s->inuse--;
}
return 0;
}